package com.fs.generator;

import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.fs.generator.db.dialect.MetadataLoadDialect;
import com.fs.generator.db.metadata.TableMetadata;
import com.fs.generator.module.ModuleGenerator;
import com.fs.generator.parser.NamesHold;
import com.fs.generator.parser.NamesResolver;

import lombok.Data;
import lombok.extern.log4j.Log4j2;

@Log4j2
@Data
public class DefaultCodeGeneratorFactory implements CodeGeneratorFactory, ApplicationContextAware {

	private GenerateConfiguration generateConfiguration;

	private MetadataLoadDialect metadataLoadDialect;

	private NamesResolver namesResolver;

	private ApplicationContext applicationContext;

	@Override
	public void generateTable(String tableName) {
		try {
			GenerateContext generateContext = loadGenerateContext(tableName);
			Map<String, ModuleGenerator> moduleGeneratorMaps = applicationContext.getBeansOfType(ModuleGenerator.class);
			log.debug("Find reigstered ModuleGenerator: {} --> ", moduleGeneratorMaps.size(), moduleGeneratorMaps);
			for (Map.Entry<String, ModuleGenerator> entry : moduleGeneratorMaps.entrySet()) {
				if (generateConfiguration.isGenerate(entry.getKey())) {
					entry.getValue().generate(generateContext);
				}
			}
			log.info("Generate from [{}] to Code/Resource/Pages success.", tableName);
		} catch (Exception e) {
			log.error("Generate Table fail. --> tableName: {}", tableName, e);
		}

	}

	@Override
	public void generateTables(String... tableNames) {
		for (String tableName : tableNames) {
			generateTable(tableName);
		}
	}

	protected GenerateContext loadGenerateContext(String tableName) {
		TableMetadata tableMetadata = getMetadataLoadDialect().loadTableMetadata(tableName);
		String entityIdDeclare = getMetadataLoadDialect().getEntityIdDeclare(tableName);
		NamesHold namesHold = namesResolver.resolve(tableName);
		GenerateContext generateContext = new GenerateContext();
		log.debug("Configurations:\n{}", getGenerateConfiguration());
		generateContext.setConfiguration(getGenerateConfiguration());
		generateContext.setTable(tableMetadata);
		generateContext.setEntityIdDeclare(entityIdDeclare);
		generateContext.setNames(namesHold);
		return generateContext;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

}
